home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / flex / flexs237.zoo / gen.c < prev    next >
C/C++ Source or Header  |  1991-03-29  |  32KB  |  1,337 lines

  1. /* gen - actual generation (writing) of flex scanners */
  2.  
  3. /*-
  4.  * Copyright (c) 1990 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  * 
  10.  * The United States Government has rights in this work pursuant
  11.  * to contract no. DE-AC03-76SF00098 between the United States
  12.  * Department of Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted provided
  15.  * that: (1) source distributions retain this entire copyright notice and
  16.  * comment, and (2) distributions including binaries display the following
  17.  * acknowledgement:  ``This product includes software developed by the
  18.  * University of California, Berkeley and its contributors'' in the
  19.  * documentation or other materials provided with the distribution and in
  20.  * all advertising materials mentioning features or use of this software.
  21.  * Neither the name of the University nor the names of its contributors may
  22.  * be used to endorse or promote products derived from this software without
  23.  * specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  25.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] =
  31.     "@(#) $Header: /home/horse/u0/vern/flex/RCS/gen.c,v 2.12 91/03/28 12:01:38 vern Exp $ (LBL)";
  32. #endif
  33.  
  34. #include "flexdef.h"
  35.  
  36.  
  37. /* declare functions that have forward references */
  38.  
  39. void gen_next_state PROTO((int));
  40. void genecs PROTO(());
  41. void indent_put2s PROTO((char [], char []));
  42. void indent_puts PROTO((char []));
  43.  
  44.  
  45. static int indent_level = 0; /* each level is 4 spaces */
  46.  
  47. #define indent_up() (++indent_level)
  48. #define indent_down() (--indent_level)
  49. #define set_indent(indent_val) indent_level = indent_val
  50.  
  51. /* *everything* is done in terms of arrays starting at 1, so provide
  52.  * a null entry for the zero element of all C arrays
  53.  */
  54. static char C_short_decl[] = "static const short int %s[%d] =\n    {   0,\n";
  55. static char C_long_decl[] = "static const long int %s[%d] =\n    {   0,\n";
  56. static char C_state_decl[] =
  57.     "static const yy_state_type %s[%d] =\n    {   0,\n";
  58.  
  59.  
  60. /* indent to the current level */
  61.  
  62. void do_indent()
  63.  
  64.     {
  65.     register int i = indent_level * 4;
  66.  
  67.     while ( i >= 8 )
  68.     {
  69.     putchar( '\t' );
  70.     i -= 8;
  71.     }
  72.     
  73.     while ( i > 0 )
  74.     {
  75.     putchar( ' ' );
  76.     --i;
  77.     }
  78.     }
  79.  
  80.  
  81. /* generate the code to keep backtracking information */
  82.  
  83. void gen_backtracking()
  84.  
  85.     {
  86.     if ( reject || num_backtracking == 0 )
  87.     return;
  88.  
  89.     if ( fullspd )
  90.     indent_puts( "if ( yy_current_state[-1].yy_nxt )" );
  91.     else
  92.     indent_puts( "if ( yy_accept[yy_current_state] )" );
  93.  
  94.     indent_up();
  95.     indent_puts( "{" );
  96.     indent_puts( "yy_last_accepting_state = yy_current_state;" );
  97.     indent_puts( "yy_last_accepting_cpos = yy_cp;" );
  98.     indent_puts( "}" );
  99.     indent_down();
  100.     }
  101.  
  102.  
  103. /* generate the code to perform the backtrack */
  104.  
  105. void gen_bt_action()
  106.  
  107.     {
  108.     if ( reject || num_backtracking == 0 )
  109.     return;
  110.  
  111.     set_indent( 3 );
  112.  
  113.     indent_puts( "case 0: /* must backtrack */" );
  114.     indent_puts( "/* undo the effects of YY_DO_BEFORE_ACTION */" );
  115.     indent_puts( "*yy_cp = yy_hold_char;" );
  116.  
  117.     if ( fullspd || fulltbl )
  118.     indent_puts( "yy_cp = yy_last_accepting_cpos + 1;" );
  119.     else
  120.     /* backtracking info for compressed tables is taken \after/
  121.      * yy_cp has been incremented for the next state
  122.      */
  123.     indent_puts( "yy_cp = yy_last_accepting_cpos;" );
  124.  
  125.     indent_puts( "yy_current_state = yy_last_accepting_state;" );
  126.     indent_puts( "goto yy_find_action;" );
  127.     putchar( '\n' );
  128.  
  129.     set_indent( 0 );
  130.     }
  131.  
  132.  
  133. /* genctbl - generates full speed compressed transition table
  134.  *
  135.  * synopsis
  136.  *     genctbl();
  137.  */
  138.  
  139. void genctbl()
  140.  
  141.     {
  142.     register int i;
  143.     int end_of_buffer_action = num_rules + 1;
  144.  
  145.     /* table of verify for transition and offset to next state */
  146.     printf( "static const struct yy_trans_info yy_transition[%d] =\n",
  147.         tblend + numecs + 1 );
  148.     printf( "    {\n" );
  149.     
  150.     /* We want the transition to be represented as the offset to the
  151.      * next state, not the actual state number, which is what it currently is.
  152.      * The offset is base[nxt[i]] - base[chk[i]].  That's just the
  153.      * difference between the starting points of the two involved states
  154.      * (to - from).
  155.      *
  156.      * first, though, we need to find some way to put in our end-of-buffer
  157.      * flags and states.  We do this by making a state with absolutely no
  158.      * transitions.  We put it at the end of the table.
  159.      */
  160.     /* at this point, we're guaranteed that there's enough room in nxt[]
  161.      * and chk[] to hold tblend + numecs entries.  We need just two slots.
  162.      * One for the action and one for the end-of-buffer transition.  We
  163.      * now *assume* that we're guaranteed the only character we'll try to
  164.      * index this nxt/chk pair with is EOB, i.e., 0, so we don't have to
  165.      * make sure there's room for jam entries for other characters.
  166.      */
  167.  
  168.     base[lastdfa + 1] = tblend + 2;
  169.     nxt[tblend + 1] = end_of_buffer_action;
  170.     chk[tblend + 1] = numecs + 1;
  171.     chk[tblend + 2] = 1; /* anything but EOB */
  172.     nxt[tblend + 2] = 0; /* so that "make test" won't show arb. differences */
  173.  
  174.     /* make sure every state has a end-of-buffer transition and an action # */
  175.     for ( i = 0; i <= lastdfa; ++i )
  176.     {
  177.     register int anum = dfaacc[i].dfaacc_state;
  178.  
  179.     chk[base[i]] = EOB_POSITION;
  180.     chk[base[i] - 1] = ACTION_POSITION;
  181.     nxt[base[i] - 1] = anum;    /* action number */
  182.     }
  183.  
  184.     for ( i = 0; i <= tblend; ++i )
  185.     {
  186.     if ( chk[i] == EOB_POSITION )
  187.         transition_struct_out( 0, base[lastdfa + 1] - i );
  188.  
  189.     else if ( chk[i] == ACTION_POSITION )
  190.         transition_struct_out( 0, nxt[i] );
  191.  
  192.     else if ( chk[i] > numecs || chk[i] == 0 )
  193.         transition_struct_out( 0, 0 );        /* unused slot */
  194.  
  195.     else    /* verify, transition */
  196.         transition_struct_out( chk[i], base[nxt[i]] - (i - chk[i]) );
  197.     }
  198.  
  199.  
  200.     /* here's the final, end-of-buffer state */
  201.     transition_struct_out( chk[tblend + 1], nxt[tblend + 1] );
  202.     transition_struct_out( chk[tblend + 2], nxt[tblend + 2] );
  203.  
  204.     printf( "    };\n" );
  205.     printf( "\n" );
  206.  
  207.     /* table of pointers to start states */
  208.     printf( "static const struct yy_trans_info *yy_start_state_list[%d] =\n",
  209.         lastsc * 2 + 1 );
  210.     printf( "    {\n" );
  211.  
  212.     for ( i = 0; i <= lastsc * 2; ++i )
  213.     printf( "    &yy_transition[%d],\n", base[i] );
  214.  
  215.     dataend();
  216.  
  217.     if ( useecs )
  218.     genecs();
  219.     }
  220.  
  221.  
  222. /* generate equivalence-class tables */
  223.  
  224. void genecs()
  225.  
  226.     {
  227.     register int i, j;
  228.     static char C_char_decl[] = "static const %s %s[%d] =\n    {   0,\n";
  229.     int numrows;
  230.     Char clower();
  231.  
  232.     if ( numecs < csize )
  233.     printf( C_char_decl, "YY_CHAR", "yy_ec", csize );
  234.     else
  235.     printf( C_char_decl, "short", "yy_ec", csize );
  236.  
  237.     for ( i = 1; i < csize; ++i )
  238.     {
  239.     if ( caseins && (i >= 'A') && (i <= 'Z') )
  240.         ecgroup[i] = ecgroup[clower( i )];
  241.  
  242.     ecgroup[i] = abs( ecgroup[i] );
  243.     mkdata( ecgroup[i] );
  244.     }
  245.  
  246.     dataend();
  247.  
  248.     if ( trace )
  249.     {
  250.     char *readable_form();
  251.  
  252.     fputs( "\n\nEquivalence Classes:\n\n", stderr );
  253.  
  254.     numrows = csize / 8;
  255.  
  256.     for ( j = 0; j < numrows; ++j )
  257.         {
  258.         for ( i = j; i < csize; i = i + numrows )
  259.         {
  260.         fprintf( stderr, "%4s = %-2d", readable_form( i ), ecgroup[i] );
  261.  
  262.         putc( ' ', stderr );
  263.         }
  264.  
  265.         putc( '\n', stderr );
  266.         }
  267.     }
  268.     }
  269.  
  270.  
  271. /* generate the code to find the action number */
  272.  
  273. void gen_find_action()
  274.  
  275.     {
  276.     if ( fullspd )
  277.     indent_puts( "yy_act = yy_current_state[-1].yy_nxt;" );
  278.  
  279.     else if ( fulltbl )
  280.     indent_puts( "yy_act = yy_accept[yy_current_state];" );
  281.  
  282.     else if ( reject )
  283.     {
  284.     indent_puts( "yy_current_state = *--yy_state_ptr;" );
  285.     indent_puts( "yy_lp = yy_accept[yy_current_state];" );
  286.  
  287.     puts( "find_rule: /* we branch to this label when backtracking */" );
  288.  
  289.     indent_puts( "for ( ; ; ) /* until we find what rule we matched */" );
  290.  
  291.     indent_up();
  292.  
  293.     indent_puts( "{" );
  294.  
  295.     indent_puts( "if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )" );
  296.     indent_up();
  297.     indent_puts( "{" );
  298.     indent_puts( "yy_act = yy_acclist[yy_lp];" );
  299.  
  300.     if ( variable_trailing_context_rules )
  301.         {
  302.         indent_puts(